package com.xh.baselibrary.utils.net;


import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;

import androidx.annotation.RequiresApi;

import com.xh.baselibrary.log.XLog;

import java.util.Iterator;

import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.GET;
import retrofit2.http.Headers;
import retrofit2.http.Url;

public class RequestNetWorker {
    public interface RequestNetListener {
        void onNetValid(boolean isValid);
    }

    private static final String TAG = RequestNetWorker.class.getSimpleName();
    private static final int RETRY_TIME = 15 * 1000;//正常情况下的间隔时间
    private static final int ERROR_RETRY_TIME = 8 * 1000;//错误情况下的间隔时间
    private String[] mHost;
    private Handler mHandler;
    private RequestNetListener mListener;

    private class HostResult {
        private String mHost;
        private boolean mResult;

        private HostResult(String mHost, boolean mResult) {
            this.mHost = mHost;
            this.mResult = mResult;
        }
    }

    private LimitQueue<HostResult> mHostResults;
    private boolean mNetWorkValid = true;
    private volatile int currHostIndex = 0;
    private volatile HandlerThread mHandlerThread;

    public RequestNetWorker(String[] hosts, RequestNetListener listener) {
        for (String host : hosts) {
            XLog.i(TAG, "host = " + host);
            if (!host.contains("http")) {
                throw new UnsupportedOperationException("");
            }
        }
        mHost = hosts;
        mHostResults = new LimitQueue<>(mHost.length * 5);
        mListener = listener;
    }

    public void start() {
        if (mHandlerThread == null) {
            mHandlerThread = new HandlerThread("RequstNetWorker");
            mHandlerThread.start();
        }
        mHandler = new Handler(mHandlerThread.getLooper());
        mHandler.removeCallbacks(mCheckNetRun);
        mHandler.post(mCheckNetRun);
        mNetWorkValid = true;
        notifyNetWorkValidState(mNetWorkValid);
    }

    public void stop() {
        mHandler.removeCallbacks(mCheckNetRun);
        if (mHandlerThread != null) {
            mHandlerThread.quit();
            mHandlerThread = null;
        }
    }

    private boolean historyNetWorkValid() {
        Iterator<HostResult> iterator = mHostResults.iterator();
        int suc = 0;
        while (iterator.hasNext()) {
            HostResult hr = iterator.next();
            if (hr.mResult) {
                suc++;
            }
        }
        return suc > 0;
    }

    private void notifyNetWorkValidState(boolean netWorkValid) {
        if (mNetWorkValid != netWorkValid) {
            if (mListener != null) {
                mListener.onNetValid(netWorkValid);
            }
            mNetWorkValid = netWorkValid;

        }
    }

    private Runnable mCheckNetRun = new Runnable() {
        @Override
        public void run() {
            checkNetWorkValid();
        }
    };

    private void checkNetWorkValid() {
        String host = getHost();
        Retrofit retrofit = new Retrofit.Builder().baseUrl("host").client(new OkHttpClient()).addConverterFactory(GsonConverterFactory.create()).build();
        EvaluatorServer server = retrofit.create(EvaluatorServer.class);
        Call<ResponseBody> call = server.evaluatorWord("");
        call.enqueue(new RetrofitCallback(host));
    }

    private class ResponseNotify implements Runnable {
        private HostResult mResult;

        private ResponseNotify(HostResult mResult) {
            this.mResult = mResult;
        }

        @RequiresApi(api = Build.VERSION_CODES.P)
        @Override
        public void run() {
            mHostResults.offer(mResult);
            notifyNetWorkValidState(mResult.mResult || historyNetWorkValid());
            mHandler.removeCallbacks(mCheckNetRun);
            mHandler.postDelayed(mCheckNetRun, mResult.mResult ? RETRY_TIME : ERROR_RETRY_TIME);
        }
    }

    private class RetrofitCallback implements Callback<ResponseBody> {
        private String mhost;

        private RetrofitCallback(String mhost) {
            this.mhost = mhost;
        }


        @Override
        public void onResponse(retrofit2.Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
            if (response != null && response.code() == 200) {
                mHandler.post(new ResponseNotify(new HostResult(mhost, true)));
            } else {
                mHandler.post(new ResponseNotify(new HostResult(mhost, false)));
                XLog.i(TAG, "body response not ok ");
            }
        }

        @Override
        public void onFailure(retrofit2.Call<ResponseBody> call, Throwable t) {
            mHandler.post(new ResponseNotify(new HostResult(mhost, false)));
            XLog.i(TAG, "body response onFailure");
        }
    }

    interface EvaluatorServer {
        @Headers({"charset:utf-8"})
        @GET
        retrofit2.Call<ResponseBody> evaluatorWord(@Url String url);
    }

    private String getHost() {

        if (currHostIndex >= mHost.length) {
            currHostIndex = 0;
        }
        String host = mHost[currHostIndex++];
        return host;
    }
}
